package com.seewo.dubbo.debugger.core;

import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;

import java.lang.reflect.Method;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;

import static java.util.concurrent.Executors.newFixedThreadPool;

/**
 * @author chenliangliang
 * @date 2018/7/26
 */
@Slf4j
public class ApiCollector implements ApplicationListener<ContextRefreshedEvent> {

    private static final String DUBBO_SERVICE_BEAN_CLASS = "com.alibaba.dubbo.config.spring.ServiceBean";
    private static final String SERVICE_BEAN_METHOD_GETINTERFACE = "getInterface";


    private void loadApi(ApplicationContext ctx) {
        log.info("开始扫描接口...");
        long time = System.currentTimeMillis();
        Class<?> serviceBeanClass;
        Method getInterfaceMethod;
        try {
            serviceBeanClass = Class.forName(DUBBO_SERVICE_BEAN_CLASS);
            getInterfaceMethod = serviceBeanClass.getMethod(SERVICE_BEAN_METHOD_GETINTERFACE);
        } catch (ClassNotFoundException | NoSuchMethodException e) {
            log.error("请添加dubbo依赖", e);
            return;
        }
        ApiContext.setApplicationContext(ctx);
        String[] beanNames = ctx.getBeanNamesForType(serviceBeanClass);
        if (beanNames == null || beanNames.length == 0) {
            log.warn("don't find any dubbo service bean in applicationContext");
            return;
        }
        CountDownLatch latch = new CountDownLatch(beanNames.length);
        ApiContext.setLatch(latch);
        ExecutorService executorService = newFixedThreadPool(beanNames.length);
            for (String beanName : beanNames) {
            try {
                Object serviceBeanObj = ctx.getBean(beanName);
                String result = (String) getInterfaceMethod.invoke(serviceBeanObj);
                executorService.execute(() -> {
                    scanInterface(result);
                    latch.countDown();
                });
            } catch (Exception e) {
                log.error("get dubbo service-interface error", e);
            }
        }
        executorService.shutdown();

        time = System.currentTimeMillis() - time;
        log.info("扫描接口信息完成，耗时：" + time + " ms");
        //注册Dubbo服务
        ApiServiceRegister register = new ApiServiceRegister();
        register.register(ctx);
    }

    /**
     * 扫描接口
     *
     * @param interfaceStr 接口全名
     */
    private void scanInterface(String interfaceStr) {
        try {
            Class<?> interfaceClass = Class.forName(interfaceStr);
            ApiContext.addApi(interfaceClass);
        } catch (ClassNotFoundException e) {
            log.warn("interface {} not exist", interfaceStr);
        }
    }

    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        loadApi(event.getApplicationContext());
    }


}
